Использование WebTransport

WebTransport — это API, предлагающий двунаправленный клиент-серверный обмен сообщениями с низкой задержкой. Узнайте больше о вариантах его использования и о том, как дать отзыв о будущем реализации.

Фон

Что такое WebTransport?

WebTransport — это веб-API, использующий протокол HTTP/3 в качестве двунаправленного транспорта. Он предназначен для двусторонней связи между веб-клиентом и сервером HTTP/3. Он поддерживает отправку данных как ненадежно через свои API датаграмм , так и надежно через свои API потоков .

Дейтаграммы идеально подходят для отправки и получения данных, которым не нужны надежные гарантии доставки. Отдельные пакеты данных ограничены по размеру максимальным блоком передачи (MTU) базового соединения и могут быть переданы или не переданы успешно, а если они переданы, то могут прибыть в произвольном порядке. Эти характеристики делают API дейтаграмм идеальными для передачи данных с малой задержкой и наилучшими усилиями. Вы можете думать о дейтаграммах как о сообщениях протокола пользовательских дейтаграмм (UDP) , но зашифрованных и с контролем перегрузки.

API потоков, напротив, обеспечивают надежную упорядоченную передачу данных. Они хорошо подходят для сценариев, где вам нужно отправить или получить один или несколько потоков упорядоченных данных. Использование нескольких потоков WebTransport аналогично установлению нескольких TCP -соединений, но поскольку HTTP/3 использует более легкий протокол QUIC под капотом, их можно открывать и закрывать без особых накладных расходов.

Варианты использования

Это небольшой список возможных способов использования WebTransport разработчиками.

  • Отправка состояния игры на сервер через регулярные интервалы времени с минимальной задержкой посредством небольших, ненадежных и нерегулярных сообщений.
  • Прием медиапотоков с сервера с минимальной задержкой, независимо от других потоков данных.
  • Получение уведомлений с сервера при открытой веб-странице.

Нам интересно узнать больше о том, как вы планируете использовать WebTransport.

Поддержка браузера

Browser Support

  • Хром: 97.
  • Край: 97.
  • Firefox: 114.
  • Safari: не поддерживается.

Source

Как и в случае со всеми функциями, не имеющими универсальной поддержки браузеров, наилучшей практикой является защитное кодирование с помощью обнаружения функций .

Текущий статус

Шаг Статус
1. Создать пояснитель Полный
2. Создать первоначальный проект спецификации Полный
3. Соберите отзывы и доработайте дизайн Полный
4. Исходный тест Полный
5. Запуск Хром 97

Связь WebTransport с другими технологиями

Является ли WebTransport заменой WebSockets?

Возможно. Существуют случаи, когда WebSockets или WebTransport могут быть допустимыми протоколами связи.

Коммуникации WebSockets моделируются вокруг одного, надежного, упорядоченного потока сообщений, что хорошо для некоторых типов коммуникационных потребностей. Если вам нужны эти характеристики, то API потоков WebTransport также могут их предоставить. Для сравнения, API датаграмм WebTransport обеспечивают доставку с низкой задержкой, без гарантий надежности или упорядоченности, поэтому они не являются прямой заменой WebSockets.

Использование WebTransport через API датаграмм или через несколько параллельных экземпляров API Streams означает, что вам не нужно беспокоиться о блокировке начала очереди , которая может быть проблемой для WebSockets. Кроме того, есть преимущества в производительности при установлении новых соединений, поскольку базовое рукопожатие QUIC быстрее, чем запуск TCP через TLS.

WebTransport является частью новой спецификации проекта, и как таковая экосистема WebSocket вокруг клиентских и серверных библиотек в настоящее время намного более надежна. Если вам нужно что-то, что работает "из коробки" с обычными настройками сервера и с широкой поддержкой веб-клиентов, WebSockets сегодня является лучшим выбором.

WebTransport — это то же самое, что и API сокетов UDP?

Нет. WebTransport не является API сокета UDP . Хотя WebTransport использует HTTP/3, который, в свою очередь, использует UDP «под капотом», WebTransport имеет требования к шифрованию и контролю перегрузки, которые делают его чем-то большим, чем просто API сокета UDP.

Является ли WebTransport альтернативой каналам данных WebRTC?

Да, для клиент-серверных соединений. WebTransport имеет много общих свойств с каналами данных WebRTC , хотя базовые протоколы отличаются.

Как правило, запуск HTTP/3-совместимого сервера требует меньше настройки и конфигурации, чем поддержка сервера WebRTC, которая включает понимание нескольких протоколов ( ICE , DTLS и SCTP ) для получения работающего транспорта. WebRTC влечет за собой гораздо больше движущихся частей, которые могут привести к сбоям в согласовании клиент/сервер.

API WebTransport был разработан с учетом вариантов использования веб-разработчиками и должен больше походить на написание кода современной веб-платформы, чем на использование интерфейсов каналов данных WebRTC. В отличие от WebRTC , WebTransport поддерживается внутри Web Workers , что позволяет вам выполнять клиент-серверные коммуникации независимо от заданной HTML-страницы. Поскольку WebTransport предоставляет интерфейс, совместимый со Streams , он поддерживает оптимизации вокруг backpressure .

Однако если у вас уже есть работающая клиент-серверная конфигурация WebRTC, которая вас устраивает, переход на WebTransport может не дать особых преимуществ.

Попробуйте это

Лучший способ поэкспериментировать с WebTransport — запустить совместимый HTTP/3-сервер. Затем вы можете использовать эту страницу с базовым клиентом JavaScript, чтобы опробовать клиент-серверную связь.

Кроме того, поддерживаемый сообществом эхо-сервер доступен по адресу webtransport.day .

Использование API

WebTransport был разработан на основе современных примитивов веб-платформ, таких как Streams API . Он в значительной степени опирается на promises и хорошо работает с async и await .

Текущая реализация WebTransport в Chromium поддерживает три различных типа трафика: датаграммы, а также однонаправленные и двунаправленные потоки.

Подключение к серверу

Вы можете подключиться к серверу HTTP/3, создав экземпляр WebTransport . Схема URL должна быть https . Вам необходимо явно указать номер порта.

Вам следует использовать обещание ready , чтобы дождаться установления соединения. Это обещание не будет выполнено, пока настройка не будет завершена, и будет отклонено, если соединение не будет установлено на этапе QUIC/TLS.

closed обещание выполняется, когда соединение закрывается нормально, и отклоняется, если закрытие было неожиданным.

Если сервер отклоняет соединение из-за ошибки указания клиента (например, путь URL недействителен), то это приводит к отклонению closed , в то время как ready остается неразрешенным.

const url = 'https://example.com:4999/foo/bar';
const transport = new WebTransport(url);

// Optionally, set up functions to respond to
// the connection closing:
transport.closed.then(() => {
  console.log(`The HTTP/3 connection to ${url} closed gracefully.`);
}).catch((error) => {
  console.error(`The HTTP/3 connection to ${url} closed due to ${error}.`);
});

// Once .ready fulfills, the connection can be used.
await transport.ready;

API-интерфейсы датаграмм

Подключив экземпляр WebTransport к серверу, вы можете использовать его для отправки и получения дискретных битов данных, известных как датаграммы .

writeable геттер возвращает WritableStream , который веб-клиент может использовать для отправки данных на сервер. readable геттер возвращает ReadableStream , позволяя вам прослушивать данные с сервера. Оба потока по своей сути ненадежны, поэтому возможно, что записанные вами данные не будут получены сервером, и наоборот.

Оба типа потоков используют экземпляры Uint8Array для передачи данных.

// Send two datagrams to the server.
const writer = transport.datagrams.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);

// Read datagrams from the server.
const reader = transport.datagrams.readable.getReader();
while (true) {
  const {value, done} = await reader.read();
  if (done) {
    break;
  }
  // value is a Uint8Array.
  console.log(value);
}

API потоков

После подключения к серверу вы также можете использовать WebTransport для отправки и получения данных через его API-интерфейсы Streams.

Каждый фрагмент всех потоков — это Uint8Array . В отличие от API Datagram, эти потоки надежны. Но каждый поток независим, поэтому порядок данных в потоках не гарантируется.

WebTransportSendStream

WebTransportSendStream создается веб-клиентом с помощью метода createUnidirectionalStream() экземпляра WebTransport , который возвращает обещание для WebTransportSendStream .

Используйте метод close() класса WritableStreamDefaultWriter для закрытия связанного потока HTTP/3. Браузер пытается отправить все ожидающие данные перед фактическим закрытием связанного потока.

// Send two Uint8Arrays to the server.
const stream = await transport.createUnidirectionalStream();
const writer = stream.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);
try {
  await writer.close();
  console.log('All data has been sent.');
} catch (error) {
  console.error(`An error occurred: ${error}`);
}

Аналогично используйте метод abort() класса WritableStreamDefaultWriter для отправки RESET_STREAM на сервер. При использовании abort() браузер может отбросить любые ожидающие данные, которые еще не были отправлены.

const ws = await transport.createUnidirectionalStream();
const writer = ws.getWriter();
writer.write(...);
writer.write(...);
await writer.abort();
// Not all the data may have been written.

WebTransportReceiveStream

WebTransportReceiveStream инициируется сервером. Получение WebTransportReceiveStream — это двухэтапный процесс для веб-клиента. Сначала он вызывает атрибут incomingUnidirectionalStreams экземпляра WebTransport , который возвращает ReadableStream . Каждый фрагмент этого ReadableStream , в свою очередь, является WebTransportReceiveStream , который можно использовать для чтения экземпляров Uint8Array , отправленных сервером.

async function readFrom(receiveStream) {
  const reader = receiveStream.readable.getReader();
  while (true) {
    const {done, value} = await reader.read();
    if (done) {
      break;
    }
    // value is a Uint8Array
    console.log(value);
  }
}

const rs = transport.incomingUnidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is an instance of WebTransportReceiveStream
  await readFrom(value);
}

Вы можете обнаружить закрытие потока, используя closed обещание ReadableStreamDefaultReader . Когда базовый поток HTTP/3 закрывается битом FIN , closed обещание выполняется после того, как все данные прочитаны. Когда поток HTTP/3 закрывается внезапно (например, с помощью RESET_STREAM ), closed обещание отклоняется.

// Assume an active receiveStream
const reader = receiveStream.readable.getReader();
reader.closed.then(() => {
  console.log('The receiveStream closed gracefully.');
}).catch(() => {
  console.error('The receiveStream closed abruptly.');
});

WebTransportДвунаправленный поток

WebTransportBidirectionalStream может быть создан как сервером, так и клиентом.

Веб-клиенты могут создать его с помощью метода createBidirectionalStream() экземпляра WebTransport , который возвращает обещание для WebTransportBidirectionalStream .

const stream = await transport.createBidirectionalStream();
// stream is a WebTransportBidirectionalStream
// stream.readable is a ReadableStream
// stream.writable is a WritableStream

Вы можете прослушивать WebTransportBidirectionalStream созданный сервером с атрибутом incomingBidirectionalStreams экземпляра WebTransport , который возвращает ReadableStream . Каждый фрагмент этого ReadableStream , в свою очередь, является WebTransportBidirectionalStream .

const rs = transport.incomingBidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is a WebTransportBidirectionalStream
  // value.readable is a ReadableStream
  // value.writable is a WritableStream
}

WebTransportBidirectionalStream — это просто комбинация WebTransportSendStream и WebTransportReceiveStream . Примеры из предыдущих двух разделов объясняют, как использовать каждый из них.

Еще примеры

Проект спецификации WebTransport включает в себя ряд дополнительных встроенных примеров, а также полную документацию по всем методам и свойствам.

WebTransport в DevTools Chrome

К сожалению, DevTools Chrome в настоящее время не поддерживает WebTransport. Вы можете "пометить" эту проблему Chrome , чтобы получать уведомления об обновлениях в интерфейсе DevTools.

Полифилл

Доступен полифил (или, скорее, понифилл, который предоставляет функциональность как отдельный модуль, который вы можете использовать) под названием webtransport-ponyfill-websocket , реализующий некоторые функции WebTransport. Внимательно прочитайте ограничения в README проекта, чтобы определить, подойдет ли это решение для вашего варианта использования.

Вопросы конфиденциальности и безопасности

Достоверные указания см. в соответствующем разделе проекта спецификации.

Обратная связь

Команда Chrome хочет услышать ваши мысли и опыт использования этого API.

Отзыв о дизайне API

Есть ли что-то в API, что неудобно или не работает так, как ожидалось? Или не хватает частей, которые вам нужны для реализации вашей идеи?

Сообщите о проблеме в репозитории Web Transport GitHub или добавьте свои мысли к существующей проблеме.

Проблемы с реализацией?

Вы обнаружили ошибку в реализации Chrome?

Сообщите об ошибке по адресу https://new.crbug.com . Опишите ее как можно подробнее, а также добавьте простые инструкции по ее воспроизведению.

Планируете использовать API?

Ваша публичная поддержка помогает Chrome расставлять приоритеты в функциях и показывает другим поставщикам браузеров, насколько важна их поддержка.

  • Отправьте твит @ChromiumDev , используя хэштег #WebTransport и расскажите, где и как вы его используете.

Общее обсуждение

Вы можете использовать группу Google web-transport-dev для общих вопросов или проблем, которые не попадают ни в одну из других категорий.

Благодарности

Эта статья включает информацию из WebTransport Explainer , черновой спецификации и связанных с ней проектных документов . Благодарим соответствующих авторов за предоставление этой основы.

Главное изображение в этом посте принадлежит Робину Пьеру с Unsplash.